<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Controller\admin;

use App\Exception\BusinessException;
use App\Model\Admin\Upload;
use Exception;
use Hyperf\HttpServer\Annotation\AutoController;
use Psr\Http\Message\ResponseInterface;
use Hyperf\DbConnection\Model\Model;
/**
 * 附件管理.
 */
#[AutoController]
class UploadController extends Crud
{
    /**
     * @var Upload
     */
    protected Model $model;

    /**
     * 只返回当前管理员数据.
     */
    protected string $dataLimit = 'personal';

    /**
     * 构造函数.
     */
    public function __construct()
    {
        $this->model = new Upload();
        parent::__construct();
    }

    /**
     * 浏览.
     */
    public function index(): ResponseInterface
    {
        $render = $this->render;
        return $render->render('upload/index');
    }

    /**
     * 浏览附件.
     */
    public function attachment(): ResponseInterface
    {
        $render = $this->render;
        return $render->render('upload/attachment');
    }

    /**
     * 查询附件.
     */
    public function select(): ResponseInterface
    {
        [$where, $format, $limit, $field, $order] = $this->selectInput();
        if (! empty($where['ext']) && is_string($where['ext'])) {
            $where['ext'] = ['in', explode(',', $where['ext'])];
        }
        if (! empty($where['name']) && is_string($where['name'])) {
            $where['name'] = ['like', "%{$where['name']}%"];
        }
        $query = $this->doSelect($where, $field, $order);
        return $this->doFormat($query, $format, $limit);
    }

    /**
     * 更新附件.
     */
    public function update(): ResponseInterface
    {
        $request = $this->request;
        $render = $this->render;
        if ($request->isMethod('get')) {
            return $render->render('upload/update');
        }
        return parent::update();
    }

    /**
     * 添加附件.
     */
    public function insert(): ResponseInterface
    {
        $request = $this->request;
        $render = $this->render;
        if ($request->isMethod('get')) {
            return $render->render('upload/insert');
        }
        $file = $request->file('__file__');
        if (! $file || ! $file->isValid()) {
            return $this->json(1, '未找到文件');
        }
        $ext = strtolower($file->getExtension());
//        if (! in_array($ext, ['jpg', 'jpeg', 'gif', 'png'])) {
//            return $this->json(2, '仅支持 jpg jpeg gif png格式');
//        }
        $ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp'];
        if (in_array($ext, $ext_forbidden_map)) {
            throw new BusinessException(1, '不支持该格式的文件上传');
        }

        //上传文件最大大小,单位M
        $maxSize = 10;
        //检测文件大小
        if ($file->getSize() > $maxSize * 1024 * 1024) {
            return $this->json(2, '文件大小超出指定范围');
        }
        $relative_path = '/upload/file/' . date('Ym');
        $real_path = BASE_PATH . "/public{$relative_path}";
        if (! is_dir($real_path)) {
            mkdir($real_path, 0777, true);
        }
        $name = bin2hex(pack('Nn', time(), random_int(1, 65535)));
        $ext = $file->getExtension();
        $new_path = $real_path."/".$name.".{$ext}";
        if (!is_file($new_path)){
            file_put_contents($new_path,file_get_contents($file->getRealPath()));
        }
        $upload = new Upload();
        $upload->name = $name;
        $upload->url="{$relative_path}/".$name.".{$ext}";
        $upload->file_size=$file->getSize();
        $upload->mime_type=$file->getMimeType();
        $upload->image_width=100;
        $upload->image_height=100;
        $upload->ext=$ext;
        $upload->category = $request->post('category');
        $upload->save();
        return $this->json(0, '上传成功', [
            'url' => "{$relative_path}/".$name.".{$ext}",
            'name' => $name,
            'size' => $file->getSize(),
        ]);
    }

    /**
     * 上传文件.
     */
    public function file(): ResponseInterface
    {
        $request = $this->request;
        $file = $request->file('__file__');
        if (! $file || ! $file->isValid()) {
            return $this->json(1, '未找到文件');
        }
        $img_exts = [
            'jpg',
            'jpeg',
            'png',
            'gif',
        ];
        if (in_array($file->getUploadExtension(), $img_exts)) {
            return $this->image();
        }
        $data = $this->base($request, BASE_PATH . '/upload/files/' . date('Ymd'));
        return $this->json(0, '上传成功', [
            'url' => $data['url'],
            'name' => $data['name'],
            'size' => $data['size'],
        ]);
    }

    /**
     * 上传图片.
     * @throws Exception
     */
    public function image()
    {
        $request = $this->request;
        $file = $request->file('__file__');
        if (! $file || ! $file->isValid()) {
            throw new BusinessException(1, '未找到上传文件');
        }
        $relative_path = '/upload/avatar/' . date('Ym');
        $real_path = BASE_PATH . "/public{$relative_path}";

        try {
            $name = bin2hex(pack('Nn', time(), random_int(1, 65535)));
            $ext = $file->getExtension();
            $new_path = $real_path."/".$name.".{$ext}";
            if (!is_file($new_path)){
                file_put_contents($new_path,file_get_contents($file->getRealPath()));
            }
        } catch (Exception $e) {
            return $this->error('处理图片发生错误');
        }
        return $this->json( 0,'上传成功',[
                'url' =>  "{$relative_path}/".$name.".{$ext}",
                'name' => $name,
                'size' => $file->getSize(),
            ],
        );
    }

    /**
     * 上传头像.
     */
    public function avatar(): ResponseInterface
    {
        $request = $this->request;
        if (!$request->hasFile('__file__')){
            return $this->error("没有上传图片");
        }
        $file = $request->file('__file__');
        if ($file && $file->isValid()) {
            $ext = strtolower($file->getExtension());
            if (! in_array($ext, ['jpg', 'jpeg', 'gif', 'png'])) {
                return $this->json(2, '仅支持 jpg jpeg gif png格式');
            }
            //上传文件最大大小,单位M
            $maxSize = 10;
            //检测文件大小
            if ($file->getSize() > $maxSize * 1024 * 1024) {
                return $this->json(2, '文件大小超出指定范围');
            }
//            $image = ImageManagerStatic::make($file);
//            $width = $file->width();
//            $height = $image->height();
//            $size = min($width, $height);
            $relative_path = '/upload/avatar/' . date('Ym');
            $real_path = BASE_PATH . "/public{$relative_path}";
            if (! is_dir($real_path)) {
                mkdir($real_path, 0777, true);
            }
            $name = bin2hex(pack('Nn', time(), random_int(1, 65535)));
            $ext = $file->getExtension();
            $new_path = $real_path."/".$name.".{$ext}";
            if (!is_file($new_path)){
                file_put_contents($new_path,file_get_contents($file->getRealPath()));
            }
//            $image->crop($size, $size)->resize(300, 300);
//            $path = BASE_PATH . "/public/{$relative_path}/{$name}.lg.{$ext}";
//            $image->save($path);
//
//            $image->resize(120, 120);
//            $path = BASE_PATH . "/public/{$relative_path}/{$name}.md.{$ext}";
//            $image->save($path);
//
//            $image->resize(60, 60);
//            $path = BASE_PATH . "/public/{$relative_path}/{$name}.{$ext}";
//            $image->save($path);
//
//            $image->resize(30, 30);
//            $path = BASE_PATH . "/public/{$relative_path}/{$name}.sm.{$ext}";
//            $image->save($path);

            return $this->json(
                0,
                '上传成功',
                [
                    'url' => "{$relative_path}/".$name.".{$ext}",
                ],
            );
        }
        return $this->json(1, 'file not found');
    }

    /**
     * 删除附件.
     */
    public function delete(): ResponseInterface
    {
        $request = $this->request;
        $ids = $this->deleteInput($request);
        $primary_key = $this->model->getKeyName();
        $files = $this->model->whereIn($primary_key, $ids)->get()->toArray();
        $file_list = array_map(function ($item) {
            $path = $item['url'];
            if (str_starts_with($path, '/admin')) {
                $admin_public_path = BASE_PATH . '/public';
                return $admin_public_path . str_replace('/admin', '', $item['url']);
            }
            return null;
        }, $files);
        $file_list = array_filter($file_list, function ($item) {
            return ! empty($item);
        });
        $result = parent::delete($request);
        if (($res = json_decode(json_encode($result->getBody()),true)) && $res->code === 0) {
            foreach ($file_list as $file) {
                @unlink($file);
            }
        }
        return $result;
    }

    /**
     * 获取上传数据.
     * @throws RandomException
     */
    protected function base($relative_dir): array
    {
        $request = $this->request;
        $file = $request->file('__file__');
        if (! $file || ! $file->isValid()) {
            throw new BusinessException(1, '未找到上传文件');
        }

        $admin_public_path = rtrim('', '\/');
        $base_dir = $admin_public_path ? $admin_public_path . DIRECTORY_SEPARATOR : BASE_PATH . '/public/';
        $full_dir = $base_dir . $relative_dir;
        if (! is_dir($full_dir)) {
            mkdir($full_dir, 0777, true);
        }

        $ext = $file->getExtension() ?: null;
        $mime_type = $file->getMimeType();
        $file_name = $file->getFilename();
        $file_size = $file->getSize();

        if (! $ext && $file_name === 'blob') {
            [$___image, $ext] = explode('/', $mime_type);
            unset($___image);
        }

        $ext = strtolower($ext);
        $ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp'];
        if (in_array($ext, $ext_forbidden_map)) {
            throw new BusinessException(1, '不支持该格式的文件上传');
        }

        $relative_path = $relative_dir . '/' . bin2hex(pack('Nn', time(), random_int(1, 65535))) . ".{$ext}";
        $full_path = $base_dir . $relative_path;

        if (!is_file($relative_path)){
            file_put_contents($full_path,file_get_contents($file->getRealPath()));
        }
        $image_with = $image_height = 0;
        if ($img_info = getimagesize($full_path)) {
            [$image_with, $image_height] = $img_info;
            $mime_type = $img_info['mime'];
        }
        return [
            'url' => $relative_path,
            'name' => $file_name,
            'realpath' => $full_path,
            'size' => $file_size,
            'mime_type' => $mime_type,
            'image_with' => $image_with,
            'image_height' => $image_height,
            'ext' => $ext,
        ];
    }
}
